package triangulation;

import java.util.ArrayList;

import sample.Edge;
import sample.Vertex;

//Dcel representation for a given polygon. 
public class DCEL {
	public ArrayList<Edge> edgeList;
	public ArrayList<Vertex> V1;
	public ArrayList<Vertex> V2;
	public ArrayList<Edge> predE;
	public ArrayList<Edge> nextE;
	public boolean orientation;
	
	public DCEL(){
		edgeList = new ArrayList<Edge>();
		V1 = new ArrayList<Vertex>();
		V2 = new ArrayList<Vertex>();
		predE = new ArrayList<Edge>();
		nextE = new ArrayList<Edge>();
	}
	
	public DCEL(DCEL dcel){
		edgeList = new ArrayList<Edge>(dcel.edgeList);
		V1 = new ArrayList<Vertex>(dcel.V1);
		V2 = new ArrayList<Vertex>(dcel.V2);
		predE = new ArrayList<Edge>(dcel.predE);
		nextE = new ArrayList<Edge>(dcel.nextE);
		orientation = dcel.orientation;
		
	}
	
	private void generateEdgeList(Polygon polygon){
		int cnt = 0 ;
		
		int firstIndex = 0;		
		int nextIndex = polygon.getVertices().indexOf(polygon.getAdjList().get(0).get(0));
		
		while(cnt < polygon.getVertices().size()){
			
			edgeList.add(new Edge(polygon.getVertices().get(firstIndex), polygon.getVertices().get(nextIndex)));

			int first = firstIndex;
			firstIndex = nextIndex;
			
			for(int j = 0 ; j < polygon.getAdjList().get(firstIndex).size() ; j++){
				if(polygon.getAdjList().get(firstIndex).get(j) != polygon.getVertices().get(first)){
					nextIndex = polygon.getVertices().indexOf(polygon.getAdjList().get(firstIndex).get(j));
					break;
				}
			}
			
			cnt++;
		}

	}
	
	private void generateV1(){
		for(int i = 0 ; i < edgeList.size() ; i++){
			V1.add(edgeList.get(i).getSource());
		}
	}
	
	private void generateV2(){
		for(int i = 0 ; i < edgeList.size() ; i++){
			V2.add(edgeList.get(i).getTarget());
		}
	}
	
	private void generatePredE(Polygon polygon){
		for(int i = 0 ; i < edgeList.size() ; i++){
			int sourceIndex = polygon.getVertices().indexOf(V1.get(i));
			int targetIndex = polygon.getVertices().indexOf(V2.get(i));
			
			for(int j = 0 ; j < polygon.getAdjList().get(sourceIndex).size() ; j++){
				if(polygon.getVertices().indexOf(polygon.getAdjList().get(sourceIndex).get(j)) != targetIndex){
					predE.add(new Edge(V1.get(i), polygon.getAdjList().get(sourceIndex).get(j)));
					break;
				}
			}
			
		}
	}
	
	private void generateNextE(Polygon polygon){
		for(int i = 0 ; i < edgeList.size() ; i++){
			int sourceIndex = polygon.getVertices().indexOf(V1.get(i));
			int targetIndex = polygon.getVertices().indexOf(V2.get(i));
			
			for(int j = 0 ; j < polygon.getAdjList().get(targetIndex).size() ; j++){
				if(polygon.getVertices().indexOf(polygon.getAdjList().get(targetIndex).get(j)) != sourceIndex){
					nextE.add(new Edge(V2.get(i), polygon.getAdjList().get(targetIndex).get(j)));
					break;
				}
			}
			
		}
	}
	
	public void generateDCEL(Polygon polygon){
		generateEdgeList(polygon);
		generateV1();
		generateV2();
		generatePredE(polygon);
		generateNextE(polygon);
		setOrientation();
	}
	
	//for debug purpose only
	public void printDCEL(){
		System.out.println("edge\tV1\tV2\tPredE\tNextE");		
		for(int i = 0 ; i < edgeList.size() ; i++){
			System.out.println(edgeList.get(i)+"\t"+V1.get(i)+"\t"+V2.get(i)+"\t"+predE.get(i)+"\t"+nextE.get(i));
		}
	}
	
//	private double angleBetweenTwoEdge(Edge e1, Edge e2){
//		double angle1 = Math.atan2(e1.getSource().getY() - e1.getTarget().getY(), 
//				e1.getSource().getX() - e1.getTarget().getX() );
//		double angle2 = Math.atan2(e2.getSource().getY() - e2.getTarget().getY(), 
//				e2.getSource().getX() - e2.getTarget().getX() );
//		double angle = (angle1 - angle2)/Math.PI*180;
//		
//		return angle < 0 ? 360 + angle : angle;
//	}
	
	
	//if clockwise return false, else return true
	private void setOrientation(){
		long sum = 0;
		
		for(int i = 0 ; i < edgeList.size() ; i++){
			sum = (long) (sum + (edgeList.get(i).getTarget().getX() - 
					edgeList.get(i).getSource().getX()) *
					(edgeList.get(i).getTarget().getY() + 
							edgeList.get(i).getSource().getY()));
		}
		orientation = sum <= 0 ? false : true;
	}
	
	public void removeVertexFromDCEL(Vertex v){
		
	}

}
